/*
Copyright (C) 2015 Marien Raat, Pieter Staal

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <sfmlFrontend.h>

using namespace sf;

SFMLFrontend::SFMLFrontend(unsigned screenSizeX, unsigned screenSizeY)
{
    screenSize = Vector2u(screenSizeX, screenSizeY);
    window = new RenderWindow(VideoMode(screenSize.x, screenSize.y), "Float");

#ifndef OS_WIN
    randomDevice = new std::random_device;
    mt = new std::mt19937((*randomDevice)());
#else
    mt = new std::mt19937(time(0));
#endif

    heightmapGenerator = new HeightmapGenerator(mt);

    mapDisplayer = new MapDisplayer(screenSize, MAP_DISPLAY_TYPE_HEIGHTMAP);

    markovNames = new MarkovNames("data/names.txt", 2, mt);
    mapDisplayer->setIslandName(markovNames->createName());

    landMapGenerator = new LandMapGenerator;
    landMapGenerator->setWaterLevel(0.45);

    dsMapSettings.size = screenSize.x;
    dsMapSettings.h = 0.45;
    dsMapSettings.mapType = MAPTYPE_ISLAND;
    dsMapSettings.overwriteOldMap = true;
    dsMapSettings.modifierFunction = customDisplacementModifier;
    heightmapGenerator->createNewMap(dsMapSettings);

    mapDisplayer->setHeightmap(heightmapGenerator->map);
}

void SFMLFrontend::start()
{
    loadFiles();

    while (window->isOpen()) {
	handleEvents();
	if (focus)
	    handleInput();
	update();
	draw();
    }
    return;
}

void SFMLFrontend::loadFiles()
{
    if (!islandNameFont.loadFromFile("fonts/DejaVuSerif.ttf"))
	std::cout << "File \"fonts/DejaVuSerif.ttf\" not found!" << std::endl
	<< "Check if you are running the program from the main project folder."
	<< std::endl;
    else
	mapDisplayer->setNamesFont(&islandNameFont);
}

void SFMLFrontend::handleEvents()
{
    Event event;
    // Only handle one of the KeyPressed events per cycle to prevent the events
    // of accumilating when a key is kept pressed.
    bool handledKeyPressedEvent = false;
    while (window->pollEvent(event)) {
	if (event.type == Event::Closed) {
	    window->close();
	}
	if (event.type == Event::KeyPressed && !handledKeyPressedEvent) {
	    handledKeyPressedEvent = true;
	    if (event.key.code == Keyboard::Escape) {
		window->close();
	    }
	    if (event.key.code == Keyboard::N) {
		heightmapGenerator->createNewMap(dsMapSettings);
		mapDisplayer->setIslandName(markovNames->createName());
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::P) {
		heightmapGenerator->pass();
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::F) {
		heightmapGenerator->finishMap();
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::C) {
		if (heightmapGenerator->isMapDone()) {
		    heightmapGenerator->createNewMap(dsMapSettings);
		    mapDisplayer->setIslandName(markovNames->createName());
		}
		heightmapGenerator->finishMap();
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::I) {
		mapDisplayer->setSmoothingType(SMOOTHING_TYPE_INTERPOLATE);
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::A) {
		mapDisplayer->setSmoothingType(SMOOTHING_TYPE_AVERAGE);
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::Num1) {
		mapDisplayer->setMapDisplayType(MAP_DISPLAY_TYPE_HEIGHTMAP);
		updateHeightmapDisplay();
	    }
	    if (event.key.code == Keyboard::Num2) {
		mapDisplayer->setMapDisplayType(MAP_DISPLAY_TYPE_SIMPLE_MAP);
		updateHeightmapDisplay();
	    }
            if (event.key.code == Keyboard::Num3) {
                mapDisplayer->setMapDisplayType(MAP_DISPLAY_TYPE_LAND_MAP);
                updateHeightmapDisplay();
            }
	}

	// Focus control
	if (event.type == Event::LostFocus)
	    focus = false;
	if (event.type == Event::GainedFocus)
	    focus = true;
    }
}

void SFMLFrontend::handleInput()
{

}

void SFMLFrontend::updateHeightmapDisplay()
{
    mapDisplayer->setHeightmapPassSize
	(heightmapGenerator->currentPassSettings
	 .passSize);
    if (mapDisplayer->getMapDisplayType() == MAP_DISPLAY_TYPE_LAND_MAP) {
        mapDisplayer->updateHeightmapDisplay();
        mapDisplayer->setLandMap
            (landMapGenerator->generateLandMap(mapDisplayer
                                               ->normalizedHeightmap,
                                               screenSize.x, screenSize.y,
                                               true));
    }
    mapDisplayer->updateDisplay();
}

void SFMLFrontend::update()
{

}

void SFMLFrontend::draw()
{
    window->clear();
    mapDisplayer->draw(window);
    window->display();
}
